//package com.zdp.config;
//
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.zdp.commons.JsonUtils;
//import com.zdp.security.filter.RestAuthenticationFilter;
//import com.zdp.security.userdetails.UserDetailsPasswordServiceImpl;
//import com.zdp.security.userdetails.UserDetailsServiceImpl;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import lombok.val;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.annotation.Order;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.MediaType;
//import org.springframework.security.config.Customizer;
//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.builders.WebSecurity;
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//import org.springframework.security.config.http.SessionCreationPolicy;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
//import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
//import org.springframework.security.crypto.password.PasswordEncoder;
//import org.springframework.security.web.authentication.AuthenticationFailureHandler;
//import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
//
//import javax.sql.DataSource;
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * @author sesshomaru
// * @date 2021/7/2
// *
// * Rest风格认证
// */
//@Configuration
//@RequiredArgsConstructor
//@Slf4j
//@Order(99)
//@EnableWebSecurity(debug = true)
//public class Base2SecurityConfig extends WebSecurityConfigurerAdapter {
//
//    private final ObjectMapper objectMapper;
//
//    private final DataSource dataSource;
//
//    private final UserDetailsServiceImpl userDetailsService;
//
//    private final UserDetailsPasswordServiceImpl userDetailsPasswordService;
//
//    // 用于配置那些路劲需要被拦截处理
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http
//                // 只关注这些"/authorize/**", "/admin/**", "/api/**" 接口
//                .requestMatchers(req -> req.mvcMatchers("/authorize/**", "/admin/**", "/api/**"))
//                // session设置为无状态的，因为Rest用不到session
//                .sessionManagement(sessionManagement -> sessionManagement
//                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
//                .authorizeRequests(authorizeRequests -> authorizeRequests
//                        .antMatchers("/authorize/**").permitAll()
//                        .antMatchers("/admin/**").hasRole("ADMIN")
//                        .antMatchers("/api/**").hasRole("USER")
//                        .anyRequest().authenticated())
//                .addFilterAt(restAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
//                // 关闭csrf，因为Rest用不到csrf
//                .csrf(csrf ->csrf.disable())
//                // 启用认证头不然被拦截的接口无法访问，不过需要携带认证头信息
//                .httpBasic(Customizer.withDefaults());
//    }
//
//    // 允许或者拒绝一些请求不同通过认证和授权即可访问资源
//    @Override
//    public void configure(WebSecurity web) throws Exception {
//        // 访问/error/**不做过滤
//        web
//                .ignoring()
//                .antMatchers( "/error/**", "/h2-console/**");
//    }
//
//    /**
//     * 替代在yml配置的登录时输入的用户名和密码
//     *
//     * @param auth
//     * @throws Exception
//     */
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth
//                .userDetailsService(userDetailsService) // 配置 AuthenticationManager 使用 userService
//                .passwordEncoder(passwordEncoder())
//                .userDetailsPasswordManager(userDetailsPasswordService); // 配置密码自动升级服务
//
//        // auth.inMemoryAuthentication() 基于内存的用户信息数据源
//        // auth.jdbcAuthentication 基于数据库的用户信息数据来源
//
///*        直接执行sql语句的方式
//auth.jdbcAuthentication()
//                .dataSource(dataSource)
//                // 用于认证用户信息
//                .usersByUsernameQuery("select username, password, enabled from zdp_users where username = ?")
//                // 获取用户拥有的权限
//                .authoritiesByUsernameQuery("select username, authority from zdp_authorities where username = ?")
//                .passwordEncoder(passwordEncoder());*/
//    }
//
//
//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        // 默认编码算法的 Id
//        val idForEncode = "bcrypt";
//        // 要支持的多种编码器
//        Map encoders = new HashMap<>();
//        encoders.put(idForEncode, new BCryptPasswordEncoder());
//        encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
//
//        return new DelegatingPasswordEncoder(idForEncode, encoders);
//    }
//
//    // 实例化自定义的Filter
//    private RestAuthenticationFilter restAuthenticationFilter() throws Exception {
//        RestAuthenticationFilter filter = new RestAuthenticationFilter(objectMapper);
//        filter.setAuthenticationSuccessHandler(jsonAuthenticationSuccessHandler());
//        filter.setAuthenticationFailureHandler(jsonAuthenticationFailureHandler());
//        filter.setAuthenticationManager(authenticationManager());
//        // filter应用在哪个路口上
//        filter.setFilterProcessesUrl("/authorize/login");
//        return filter;
//    }
//
//    private AuthenticationFailureHandler jsonAuthenticationFailureHandler() {
//        return (req, res, exp) -> {
//            res.setStatus(HttpStatus.UNAUTHORIZED.value());
//            res.setContentType(MediaType.APPLICATION_JSON_VALUE);
//            res.setCharacterEncoding("UTF-8");
//            Map<String, String> errData = new HashMap<>();
//            errData.put("title", "认证失败");
//            errData.put("details", exp.getMessage());
//            res.getWriter().println(JsonUtils.objectToJson(errData));
//        };
//    }
//
//    private AuthenticationSuccessHandler jsonAuthenticationSuccessHandler() {
//        return (req, res, auth) -> {
//            res.setStatus(HttpStatus.OK.value());
//            // 将auth对象转换为json返回回去
//            res.getWriter().println(JsonUtils.objectToJson(auth));
//            log.debug("认证成功");
//        };
//    }
//}
